package com.atguigu.spzx.product.config;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

//redis的配置类
@Configuration
public class RedisConfig {
    //我们手动管理缓存时 使用
    @Resource
    RedisTemplate redisTemplate;
    //jdk原生注解：标注的方法会在当前类的构造器调用后立即执行
    @PostConstruct
    public void init(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    }

    //spring自动缓存管理 使用缓存管理器
    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory factory){
        //缓存管理 缓存过期时间、键值序列化器、是否缓存空值

        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
//                .prefixCacheNameWith() 缓存的key的前缀名称
                .entryTtl(Duration.ofSeconds(600)) //缓存的过期时间：业务规定必须配置
                .serializeKeysWith(RedisSerializationContext
                        .SerializationPair.fromSerializer(new StringRedisSerializer())) //缓存的键的序列化器
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new GenericJackson2JsonRedisSerializer())) //缓存的值 的序列化器
//                .disableCachingNullValues()  是否缓存空值 默认缓存： 为了防止缓存穿透 可以缓存空值
                // 缓存穿透最终解决方案： 短时间缓存空值+布隆过滤器解决
                // 缓存穿透(访问数据库一定不存在的数据 穿过redis访问数据库)、击穿(单个热点key失效了 导致大量的访问此key的请求访问数据库)、雪崩(多个key同时失效了 导致大量的访问此这些key的请求访问数据库)
                ;
        return RedisCacheManager.builder(factory)
                .cacheDefaults(cacheConfiguration) //redis存储缓存的配置对象
                .build();
    }

}


//    @Bean
//    public RedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory){
//        RedisTemplate redisTemplate = new RedisTemplate<>();
//        redisTemplate.setConnectionFactory(connectionFactory);
//        redisTemplate.setKeySerializer(new StringRedisSerializer());
//        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//        return redisTemplate;
//    }